﻿using System;
using System.Threading;

namespace SocketUtil
{
    public class Poller
    {
        public Action Work;
        protected Thread mThread;
        protected ManualResetEvent mStopEvent;
        protected ManualResetEvent mPauseEvent;
        protected int Interval { get; set; }
        public string Name { get; set; }

        public Poller(string name)
        {
            Name = name;
            mThread = new Thread(MainWork)
            {
                Name = name,
                IsBackground = true,
            };
            mStopEvent = new ManualResetEvent(false);
            mPauseEvent = new ManualResetEvent(false);
            Interval = 1000;
        }

        public virtual void Start()
        {
            if ((mThread.ThreadState & ThreadState.Unstarted) != 0)
                mThread.Start();
            mStopEvent.Reset();
            mPauseEvent.Set();
        }

        public virtual void Stop()
        {
            mPauseEvent.Reset();
            mStopEvent.Set();
            mThread = new Thread(MainWork);
        }

        public virtual void Pause()
        {
            mPauseEvent.Reset();
            mStopEvent.Reset();
        }

        public virtual void Continue()
        {
            if ((mThread.ThreadState & ThreadState.Unstarted) != 0)
                mThread.Start();
            mStopEvent.Reset();
            mPauseEvent.Set();
        }

        protected virtual void MainWork()
        {
            while (true)
            {
                Thread.Sleep(Interval);
                if (mStopEvent.WaitOne(0))
                    break;
                mPauseEvent.WaitOne(-1);
                DoWork();
            }
        }

        protected void DoWork()
        {
            try
            {
                Work?.Invoke();
            }
            catch (Exception ex)
            {
                System.Diagnostics.Trace.TraceError(ex.Message);
                System.Diagnostics.Trace.TraceError(ex.StackTrace);
                System.Diagnostics.Trace.TraceError(ex.Source);
            }
        }
    }

}
